﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Animation;
using RWLib;

namespace RW_GUI
{
    /// <summary>
    /// Interaction logic for AddQueryWindow.xaml
    /// </summary>
    public partial class AddQueryWindow : Window
    {
        public bool Valid;
        private string _formula = "", _action = "";
        private int _time = 1;
        public QueryModel Model;
        private List<Fluent> _fluents;
        private List<ActionModel> _actions;
        public AddQueryWindow(List<Fluent> fluents, List<ActionModel> actions)
        {
            _fluents = fluents;
            _actions = actions;
            InitializeComponent();
            LoadCombos();
        }
        private void btn_Cancel_Click(object sender, RoutedEventArgs e)
        {
            Close();
        }
        private void btn_Save_Click(object sender, RoutedEventArgs e)
        {
            var template = GetTemplate();
            var breakingstring = template.Contains("sometimes") ? "sometimes" : "always";
            _formula = txt_Query.Text.Split(new[] { breakingstring }, StringSplitOptions.None)[0];
            if (!_fluents.Any(x => _formula.Contains(x.Name)) && !template.ToLower().Contains("executable"))
            {
                MessageBox.Show("Formula requires at least 1 fluent to be valid");
                return;
            }
            Valid = true;
            Model = new QueryModel(txt_Query.Text);
            Close();
        }
        private void btn_AddFluentEffects_Click(object sender, RoutedEventArgs e)
        {
            var fcw = new FluentChoiceWindow(_fluents, String.IsNullOrEmpty(_formula) && !_formula.Equals("/formula/"));
            fcw.ShowDialog();
            _formula += fcw.Name;
            CB_Type_SelectionChanged(null, null);
            ReplaceQueryKeywords();
        }
        private void LoadCombos()
        {
            foreach (var v in typeof(QueryTypeEnum).GetEnumNames())
            {
                CB_Type.Items.Add(new ComboBoxItem { Content = v });
            }
            CB_Type.SelectedIndex = 0;

            foreach (var v in _actions.Select(x => x.Name).Distinct())
            {
                CB_Actions.Items.Add(new ComboBoxItem { Content = v });
            }
            CB_Actions.SelectedIndex = 0;
        }
        private void CB_Type_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            var str = GetTemplate();
            txt_Query.Text = str;
            ReplaceQueryKeywords();
        }
        private string GetTemplate()
        {
            QueryTypeEnum en;
            Enum.TryParse((string)((ComboBoxItem)CB_Type.SelectedValue).Content, out en);
            var str = "";
            switch (en)
            {
                case QueryTypeEnum.AlwaysExecutable:
                    str = "always executable Sc";
                    break;
                case QueryTypeEnum.SometimesExecutable:
                    str = "sometimes executable Sc";
                    break;
                case QueryTypeEnum.AlwaysCondition:
                    str = "/formula/ always true at  /time/  during Sc";
                    break;
                case QueryTypeEnum.SometimesCondition:
                    str = "/formula/ sometimes true at  /time/  during Sc";
                    break;
                case QueryTypeEnum.AlwaysGoal:
                    str = "/formula/ always reachable after Sc";
                    break;
                case QueryTypeEnum.SometimesGoal:
                    str = "/formula/ sometimes reachable after Sc";
                    break;
                case QueryTypeEnum.ExecutableDuring:
                    str = "/action/ executable during Sc";
                    break;
            }
            return str;
        }
        private void SliderTimeValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            if (sender == null || Txt_Time == null) return;
            _time = (int)((Slider)sender).Value;
            Txt_Time.Content = ((Slider)sender).Value;
            CB_Type_SelectionChanged(null, null);
            ReplaceQueryKeywords();
        }
        private ValidationResult Validate()
        {
            var current = txt_Query.Text;
            var template = GetTemplate();
            var breakingstring = "";
            breakingstring = template.Contains("sometimes") ? "sometimes" : "always";
            template = template.Replace("/time/", _time.ToString());
            current = current.Replace("/time/", _time.ToString());
            var formula = current.Split(new[] { breakingstring }, StringSplitOptions.None)[1];
            var templateformula = template.Split(new[] { breakingstring }, StringSplitOptions.None)[1];
            return !formula.Equals(templateformula) ? new ValidationResult(false, "Incorrect query syntax") : new ValidationResult(true, "");
        }

        private void TxtQueryPreviewText(object sender, System.Windows.Input.TextCompositionEventArgs e)
        {
            var result = Validate();
            if (result.IsValid)
            {
                ValidationLabel.Content = "";
                var template = GetTemplate();
                var breakingstring = template.Contains("sometimes") ? "sometimes" : "always";
                _formula = txt_Query.Text.Split(new[] { breakingstring }, StringSplitOptions.None)[0];
                btn_Save.IsEnabled = true;
                return;
            }
            btn_Save.IsEnabled = false;
            ValidationLabel.Content = result.ErrorContent;
            ValidationLabel.Opacity = 1;
            ValidationLabel.Visibility = Visibility.Visible;
            var a = new DoubleAnimation
            {
                From = 1.0,
                To = 0.0,
                FillBehavior = FillBehavior.Stop,
                BeginTime = TimeSpan.FromSeconds(1),
                Duration = new Duration(TimeSpan.FromSeconds(0.5))
            };
            var storyboard = new Storyboard();
            storyboard.Children.Add(a);
            Storyboard.SetTarget(a, ValidationLabel);
            Storyboard.SetTargetProperty(a, new PropertyPath(OpacityProperty));
            storyboard.Completed += delegate { ValidationLabel.Visibility = Visibility.Hidden; };
            storyboard.Begin();
            e.Handled = true;
        }
        private void ReplaceQueryKeywords()
        {
            txt_Query.Text = txt_Query.Text.Replace("/time/", _time.ToString());
            txt_Query.Text = txt_Query.Text.Replace("/formula/", _formula.Trim());
            txt_Query.Text = txt_Query.Text.Replace("/action/", _action);
            txt_Query.Text.Replace("  ", " ");
        }

        private void CbActionsSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            _action = CB_Actions.SelectedValue != null ? (string)((ComboBoxItem)CB_Actions.SelectedValue).Content : "";
            ReplaceQueryKeywords();
        }

        private void txt_Query_LostFocus(object sender, RoutedEventArgs e)
        {
            var template = GetTemplate();
            var breakingstring = template.Contains("sometimes") ? "sometimes" : "always";
            _formula = txt_Query.Text.Split(new[] { breakingstring }, StringSplitOptions.None)[0];
        }
    }
}